#include "SWFTag.h"
#include "TagHandler.h"

std::string names[] = {
	"End", // 00
	"ShowFrame", // 01
	"DefineShape", // 02
	"FreeCharacter", // 03
	"PlaceObject", // 04
	"RemoveObject", // 05
	"DefineBits", // 06
	"DefineButton", // 07
	"JPEGTables", // 08
	"SetBackgroundColor", // 09
	"DefineFont", // 10
	"DefineText", // 11
	"DoAction", // 12
	"DefineFontInfo", // 13
	"DefineSound", // 14
	"StartSound", // 15
	"StopSound", // 16
	"DefineButtonSound", // 17
	"SoundStreamHead", // 18
	"SoundStreamBlock", // 19
	"DefineBitsLossless", // 20
	"DefineBitsJPEG2", // 21
	"DefineShape2", // 22
	"DefineButtonCxform", // 23
	"Protect", // 24
	"PathsArePostScript", // 25
	"PlaceObject2", // 26
	"27 (invalid)", // 27
	"RemoveObject2", // 28
	"SyncFrame", // 29
	"30 (invalid)", // 30
	"FreeAll", // 31
	"DefineShape3", // 32
	"DefineText2", // 33
	"DefineButton2", // 34
	"DefineBitsJPEG3", // 35
	"DefineBitsLossless2", // 36
	"DefineEditText", // 37
	"DefineVideo", // 38
	"DefineSprite", // 39
	"NameCharacter", // 40
	"ProductInfo", // 41
	"DefineTextFormat", // 42
	"FrameLabel", // 43
	"DefineBehavior", // 44
	"SoundStreamHead2", // 45
	"DefineMorphShape", // 46
	"FrameTag", // 47
	"DefineFont2", // 48
	"GenCommand", // 49
	"DefineCommandObj", // 50
	"CharacterSet", // 51
	"FontRef", // 52
	"DefineFunction", // 53
	"PlaceFunction", // 54
	"GenTagObject", // 55
	"ExportAssets", // 56
	"ImportAssets", // 57
	"EnableDebugger", // 58
	"DoInitAction", // 59
	"DefineVideoStream", // 60
	"VideoFrame", // 61
	"DefineFontInfo2", // 62
	"DebugID", // 63
	"EnableDebugger2", // 64
	"ScriptLimits", // 65
	"SetTabIndex", // 66
	"DefineShape4", // 67
	"68 (invalid)", // 68
	"FileAttributes", // 69
	"PlaceObject3", // 70
	"ImportAssets2", // 71
	"DoABC", // 72
	"DefineFontAlignZones", // 73
	"CSMTextSettings", // 74
	"DefineFont3", // 75
	"SymbolClass", // 76
	"Metadata", // 77
	"ScalingGrid", // 78
	"79 (invalid)", // 79
	"80 (invalid)", // 80
	"81 (invalid)", // 81
	"DoABC2", // 82
	"DefineShape4", // 83
	"DefineMorphShape2", // 84
	"85 (invalid)", // 85
	"DefineSceneAndFrameLabelData", // 86
	"DefineBinaryData", // 87
	"DefineFontName", // 88
	"89 (unknown)  ", // 89
	"90 (unknown)  ", // 90
	"DefineFont4", // 91
	"(invalid)" // end
};

SWFTag::SWFTag()
	: code(0)
	, length(0)
	, data(nullptr)
{

}

SWFTag::~SWFTag()
{
	if (data != nullptr)
		delete data;
}

void SWFTag::setData( char* data, size_t len )
{
	this->data = data;
	this->length = len;
}

void SWFTag::visit( TagHandler* )
{
	assert(false);
}

std::string SWFTag::getTagName() const
{
	return names[code];
}

void SWFTag::write( SWFOutputStream* stream )
{

}

void SWFTag::read( SWFInputStream* stream )
{

}

void SWFTag::getReferences(std::vector<SWFTag*>& back)
{
	back.insert(back.end(), _references.begin(), _references.end());
}

void SWFTag::putReference( SWFTag* tag )
{
	if (tag != nullptr)
	{
		_references.push_back(tag);
	}
}

void SWFTag::removeReference(SWFTag* tag)
{
	if (tag != nullptr)
	{
		auto itr = std::find(_references.begin(), _references.end(), tag);
		if (itr != _references.end())
			_references.erase(itr);
	}
}

void TagSetBackgroundColor::visit( TagHandler* h )
{
	h->setBackgroundColor(this);
}

void TagFrameLabel::visit( TagHandler* h )
{
	h->frameLabel(this);
}

void TagFileAttributes::visit( TagHandler* h )
{
	h->fileAttributes(this);
}

void TagEnd::visit( TagHandler* h )
{
	h->end(this);
}

void TagScriptLimits::visit( TagHandler* h )
{
	h->scriptLimits(this);
}

void TagSymbolClass::visit( TagHandler* h )
{
	h->symbolClass(this);
}

void TagImportAssets2::visit( TagHandler* h )
{
	h->importAssets2(this);
}

void TagProtect::visit( TagHandler* h )
{
	h->protect(this);
}

void TagExportAssets::visit( TagHandler* h )
{
	h->exportAssets(this);
}

void TagEnableDebugger::visit( TagHandler* h )
{
	h->enableDebugger(this);
}

void TagEnableDebugger2::visit( TagHandler* h )
{
	h->enableDebugger2(this);
}

void TagSetTabIndex::visit( TagHandler* h )
{
	h->setTabIndex(this);
}

void TagDefineScalingGrid::visit( TagHandler* h )
{
	h->defineScalingGrid(this);
}

void TagDefineSceneAndFrameLabelData::visit( TagHandler* h )
{
	h->defineSceneAndFrameLabelData(this);
}

void TagDefineShape::visit( TagHandler* h )
{
	h->defineShape(this);
}

void TagDefineShape2::visit( TagHandler* h )
{
	h->defineShape2(this);
}

void TagDefineShape3::visit( TagHandler* h )
{
	h->defineShape3(this);
}

void TagDefineShape4::visit( TagHandler* h )
{
	h->defineShape4(this);
}

void TagDefineButton::visit( TagHandler* h )
{
	h->defineButton(this);
}

void TagDefineButton2::visit( TagHandler* h )
{
	h->defineButton2(this);
}

void TagDefineButtonCxform::visit( TagHandler* h )
{
	h->defineButtonCxform(this);
}

void TagDefineButtonSound::visit( TagHandler* h )
{
	h->defineButtonSound(this);
}

void TagDefineSprite::visit( TagHandler* h )
{
	h->defineSprite(this);
}

void TagDefineMorphShape::visit( TagHandler* h )
{
	h->defineMorphShape(this);
}

void TagDefineMorphShape2::visit( TagHandler* h )
{
	h->defineMorphShape2(this);
}

void TagDefineFont::visit( TagHandler* h )
{
	h->defineFont(this);
}

void TagDefineFont2::visit( TagHandler* h )
{
	h->defineFont2(this);
}

void TagDefineFont3::visit( TagHandler* h )
{
	h->defineFont3(this);
}

void TagDefineFont4::visit( TagHandler* h )
{
	h->defineFont4(this);
}

void TagDefineFontInfo::visit( TagHandler* h )
{
	h->defineFontInfo(this);
}

void TagDefineFontInfo2::visit( TagHandler* h )
{
	h->defineFontInfo2(this);
}

void TagDefineFontAlignZones::visit( TagHandler* h )
{
	h->defineFontAlignZones(this);
}

void TagDefineFontName::visit( TagHandler* h )
{
	h->defineFontName(this);
}

void TagDefineText::visit( TagHandler* h )
{
	h->defineText(this);
}

void TagDefineText2::visit( TagHandler* h )
{
	h->defineText2(this);
}

void TagDefineEditText::visit( TagHandler* h )
{
	h->defineEditText(this);
}

void TagCSMTextSettings::visit( TagHandler* h )
{
	h->cSMTextSettings(this);
}

void TagShowFrame::visit( TagHandler* h )
{
	h->showFrame(this);
}

void TagPlaceObject::visit( TagHandler* h )
{
	h->placeObject(this);
}

void TagPlaceObject2::visit( TagHandler* h )
{
	h->placeObject2(this);
}

void TagDefineBitsJPEG2::visit( TagHandler* h )
{
	h->defineBitsJPEG2(this);
}

void TagDefineBitsJPEG3::visit( TagHandler* h )
{
	h->defineBitsJPEG3(this);
}

void TagUnknow::visit( TagHandler* h )
{
	h->unknow(this);
}

void TagDefineBinaryData::visit( TagHandler* h )
{
	h->defineBinaryData(this);
}

void TagProductInfo::visit( TagHandler* h )
{
	h->productInfo(this);
}

void TagPlaceObject3::visit( TagHandler* h )
{
	h->placeObject3(this);
}

void TagRemoveObject2::visit(TagHandler* h)
{
	h->removeObject2(this);
}

void TagRemoveObject::visit(TagHandler* h)
{
	h->removeObject(this);
}

void TagDefineBitsLossless::visit( TagHandler* handler )
{
	handler->defineBitsLossless(this);
}

void TagDefineBitsLossless2::visit( TagHandler* handler )
{
	handler->defineBitsLossless2(this);
}

void TagDefineSound::visit( TagHandler* h )
{
	h->defineSound(this);
}
